package ru.stork.vasilisa.test

import ru.stork.vasilisa.model
import model.Model._
import model.{VasilisaType, ImportDef, Namespace}
import ru.stork.vasilisa.lang
import com.yelbota.util.{Lazy, $lazy}

private[test] object makeDeclaration {

  def apply() =
    model.Declaration($lazy { makeTrait(List(), "") }, None, lang.EmptyNode())

  def apply(t: model.VasilisaType): model.Declaration = apply(t, None)

  def apply(trt: model.VasilisaType, typeParameters: Option[List[model.Type]]): model.Declaration = {
    model.Declaration(
      $lazy { trt },
      typeParameters,
      lang.EmptyNode()
    )
  }
}

private[test] object makeTrait {

  /**
   * Trait with name only
   */
  def apply(ns: List[String], name: String): model.Model = new model.Model(
    ns = new EmptyNamespace().configure(Nil, ns),
    name = name,
    node = lang.EmptyNode(),
    rawSuperType = None,
    rawProperties = Set(),
    typeParameters = Set()
  )

  /**
   * Trait with properties, typeParams and included traits
   */
  def apply(properties: Set[model.Property],
            typeParameters: Set[String],
            includedTraits: Set[model.Declaration]): model.Model =
    apply(
      makeDeclaration(),
      properties, typeParameters, includedTraits)


  /**
   * Trait with properties, typeParams, included traits and supertype
   */
  def apply(superType: model.Declaration,
            properties: Set[model.Property],
            typeParameters: Set[String],
            includedTraits: Set[model.Declaration]): model.Model =
    new model.Model(
      ns = new EmptyNamespace(),
      name = "",
      node = lang.EmptyNode(),
      rawSuperType = Some(superType),
      rawProperties = properties,
      typeParameters = typeParameters
    )
}

private[test] object makeProp {

  def apply(name: String): model.Property =
    new model.Property(
      name,
      makeDeclaration(),
      lang.EmptyNode()
    );

  def apply(name: String, parameterName: String): model.Property =
    new model.Property(
      name,
      model.Parameter(parameterName, lang.EmptyNode()),
      lang.EmptyNode()
    );
}

private[test] class EmptyNamespace(val imports:List[ImportDef], val local:List[String]) extends Namespace {
  def this() = this(List(), List())
  def addPrivateDeclarations(value: Map[String, Lazy[VasilisaType]]) = new EmptyNamespace(imports, local)
  def configure(imports: List[ImportDef], local:NsDef): Namespace = new EmptyNamespace(imports, local)
  def findTrait(name: String) = Some($lazy { makeTrait(local, name) })
}